---
title: 索引概览
description: 用不用索引，这是一个问题
---
## 索引不是万能的
数据库中的索引，就好比是一本书的目录，它可以帮助我们快速进行特定值的定位和查找，从而加快数据查询的效率。

索引就是帮助数据库管理系统高效获取数据的数据结构。

如果不使用索引，就必须进行全表扫描，直到把所有数据表都扫描完，才能找到想要的数据。既然如此，如果我们想要快速查找数据，是否只需要创建更多的索引就好了呢？

其实**索引不是万能的，在有些情况下使用索引反而会使效率变低。**

索引的价值是帮我们从海量数据中找到想要的数据，如果数据量小，那么是否使用索引对结果的影响不大。

在数据表中的数据行数比较少的情况下，比如不到 1000 行，是不需要创建索引的。另外，当数据重复度大，比如高于 10% 的时候，也不需要对这个字段使用索引。

:::tip
比如性别这个字段，就不需要对它创建索引。如果想要在 100 万行数据中查找其中的 50 万行（比如性别为男的数据），一旦创建按了索引，你需要先访问 50 万次索引，然后再访问 50 万次数据表，这样加起来的开销比不使用索引可能还要大。
:::

## 索引的种类有哪些？
虽然使用索引的本质是帮我们快速定位想要查找的数据，但实际上，索引有很多种类。

从功能逻辑上分，索引主要有 4 种，分别是普通索引、唯一索引、主键索引和全文索引。

普通索引是基础的索引，没有任何约束，主要用于提高查询效率。唯一索引就是在普通索引的基础上增加了数据唯一性的约束，在一张数据表中可以有多个唯一索引。主键索引在唯一索引的基础上增加了不为空的约束，也就是 NOT_NULL + UNIQUE,一张表里最多只有一个主键索引。
全文索引用的不多，MySQL 自带的全文索引只支持英文。我们通常可以采用专门的全文搜索引擎，比如 ES(ElasticSearch)。

其实前三种索引（普通索引、唯一索引和主键索引）都是一类索引，只不过对数据的约束性逐渐提升。在一张表中只能有一个主键约束，这是由主键索引的物理实现方式决定的，因为数据存储在文件中只能按照一种顺序进行存储，但可以有多个普通索引或者多个唯一索引。

按照物理实现方式，索引可以分为 2 种： 聚集索引和非聚集索引。我们也把非聚集索引称为二级索引或者辅助索引。

聚集索引按照主键来排序存储数据，这样在查找行的时候非常有效。

非聚集索引又是什么呢？

在数据库系统会有单独的存储空间存放非聚集索引，这些索引项是按顺序存储的，但索引指向的内容是随机存储的。也就是说系统会进行两次查找，第一次先找到索引，第二次找到索引对应的位置取出数据行。
非聚集索引不会把索引指向的内容像聚集索引一样直接放到索引的后面，而是维护单独的索引表（只维护索引，不维护索引指向的数据），为数据检索提供方便。

聚集索引指表中数据行按索引的排序方式进行存储，对查找行很有效。只有当表包含聚集索引时，表内的数据行才会按找索引列的值在磁盘上进行物理排序和存储。每一个表只能有一个聚集索引，因为数据行只能按照一个顺序排序。


聚集索引与非聚集索引的原理不同，在使用上也有一些区别：
1. 聚集索引的叶子节点存储的就是我们的数据记录，非聚集索引的叶子节点存储的是数据位置。非聚集索引不会影响数据表的物理存储顺序。
2. 一张表只能有一个聚集索引，因为只能有一种排序存储的方式，但可以有多个聚集索引，也就是多个索引目录提供数据检索。
3. 使用聚集索引的时候，数据的查询效率很高，但如果对数据进行插入、删除、更新等操作，效率会比非聚集索引低。


除了功能逻辑和物理实现方式，索引还可以按照字段个数进行划分，分成单一索引和联合索引。

索引列为一列时为单一索引；多个列组合在一起创建的索引叫做联合索引；

创建联合索引时，我们需要注意创建时的顺序问题，因为联合索引 （x,y,z） 和 （z,y,x） 在使用的时候效率可能存在差别。

联合索引存在**最左匹配原则**，也就是按照最左优先的方式进行索引的匹配。比如刚才举例的 （x,y,z）,如果查询条件是 WHERE x = 1 AND y = 2 AND z =3 ,基于可以匹配上联合索引；如果查询条件时 WHERE y = 2 ，就无法匹配上联合索引。

## 总结
使用索引可以帮助我们从海量的数据中快速定位要查找的数据 ，不过索引也存在一些问题，比如占用存储空间、降低数据库的写操作的性能等，如果有多个索引还会增加索引选择的时间。当
我们使用索引时，需要平衡索引的利（提升查询效率）与弊（维护索引所需的代价）。

![](https://img.wkq.pub/spring/7c46394b6a09ba83befe2d18e466c957.webp)
